#include "cpeopletracker.h"
#include <QMessageBox>

CPeopleTracker::CPeopleTracker(IVSModel* _ivsModel) :
    IVSControllerBase(_ivsModel)
{
}

void CPeopleTracker::run()
{
    videoPlaySpeedBoost = 0;
    if(initialize())
    {
        IplImage* frame = cvQueryFrame(capture);
        char key;
        isRunning = true;
        qWarning(qPrintable(QString("fps: %1").arg(fps)));

        /* init */
        IplImage* grayFrame  = cvCreateImage(size, IPL_DEPTH_8U, 1);
        IplImage* runningAvg = cvCreateImage(size, IPL_DEPTH_32F, 1);
        IplImage* background = cvCreateImage(size, IPL_DEPTH_8U, 1);
        IplImage* diffImage  = cvCreateImage(size, IPL_DEPTH_8U, 1);

        cvCvtColor(frame, grayFrame, CV_RGB2GRAY);
        cvCopy(grayFrame, background);
        cvCvtScale(grayFrame, runningAvg);

        int nInitBGFrame = 0; // No of frame to init BG
        QList<CvRect> objList;
        tracker = new TrackingBase();
        while(frame && isRunning){
            cvCvtColor(frame, grayFrame, CV_RGB2GRAY);

            if(nInitBGFrame++ < ivsModel->IntrudersDetectionSettings().noFrameToInitBackground) {
                cvRunningAvg(grayFrame,
                             runningAvg,
                             1.0/ivsModel->IntrudersDetectionSettings().noFrameToInitBackground);
            }else{
                cvRunningAvg(grayFrame,
                             runningAvg,
                             ivsModel->IntrudersDetectionSettings().alpha);
                cvCvtScale(runningAvg, background);
                cvAbsDiff(grayFrame, background, diffImage);

                showDebugImage(background, "background");
                showDebugImage(diffImage, "difference image");

                smartThreshold(diffImage, ivsModel->IntrudersDetectionSettings().noBin);
                showDebugImage(diffImage, "object mask");

                //Find the contours of the moving images in the frame.
                CvMemStorage* storage = cvCreateMemStorage(0);
                CvSeq* contour = 0;
                cvFindContours( diffImage, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

                //Process each moving contour in the current frame...
                objList.clear();
                for( ; contour != 0; contour = contour->h_next ){
                    //Get a bounding rectangle around the moving object.
                    CvRect bndRect = cvBoundingRect(contour, 0);
                    if(bndRect.height*bndRect.width < (int)ivsModel->IntrudersDetectionSettings().bnRectArea_min ||
                            bndRect.height*bndRect.width > (int)ivsModel->IntrudersDetectionSettings().bnRectArea_max )
                        continue;
                    objList.append(bndRect);
                }
                cvReleaseMemStorage(&storage);
                tracker->updateObjectList(objList);

                showMainImage(frame);
            }

            key = cvWaitKey(1000/fps);
            if(key == 'r')
                setupROI();

            frame = cvQueryFrame(capture);
        }
        qWarning("stoped");

        /* release */
        cvReleaseImage(&grayFrame);
        cvReleaseImage(&runningAvg);
        cvReleaseImage(&background);
        cvReleaseImage(&diffImage);
    }else
    {
        QMessageBox::warning(0,
                             "Unable to play the video",
                             "Can not capture from the video source. ",
                             QMessageBox::Ok);
    }
}

void CPeopleTracker::stop()
{
    isRunning = false;
    //    delete tracker;
    release();
}

void CPeopleTracker::showMainImage(IplImage *img)
{
    foreach (TrackingObject o, tracker->ObjectList()) {
        if(ivsModel->VerboseLevel() >= 1)
            cvRectangle(
                        img,
                        cvPoint(
                            o.Rect().x,
                            o.Rect().y),
                        cvPoint(
                            o.Rect().x + o.Rect().width,
                            o.Rect().y + o.Rect().height
                            ),
                        o.Color(),
                        1,
                        8,
                        0
                        );
        if(ivsModel->VerboseLevel() >= 2)
            for(int i = 1; i < o.Trace().length(); i++)
                cvDrawLine(img, o.Trace().at(i-1), o.Trace().at(i), o.Color(), 2);
    }
    foreach (TrackingObject o, tracker->PredictedObjectList()) {
            cvRectangle(
                        img,
                        cvPoint(
                            o.Rect().x,
                            o.Rect().y),
                        cvPoint(
                            o.Rect().x + o.Rect().width,
                            o.Rect().y + o.Rect().height
                            ),
                        cvScalar(200),
                        1,
                        8,
                        0
                        );
    }


    if(!isCreatedNamedWindow){
        cvNamedWindow(ivsModel->CurrentVideoSource().SourceName(),0);
        isCreatedNamedWindow = false;
    }

    cvShowImage(ivsModel->CurrentVideoSource().SourceName(), img);
}
